[IA64] Expand memory_op for PV-on-HVM on IPF
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 1 Sep 2006 14:46:02 +0000 (08:46 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 1 Sep 2006 14:46:02 +0000 (08:46 -0600)
Signed-off-by: Tsunehisa Doi <Doi.Tsunehisa@jp.fujitsu.com>
Signed-off-by: Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com>
xen/arch/ia64/xen/mm.c
xen/arch/ia64/xen/vhpt.c

index 326e66c8a39ea29ad77ee3faebb31ac8b0c18286..e00a71599cf755f3055e950146404ad9ee0248de 100644 (file)
 #include <asm/vcpu.h>
 #include <asm/shadow.h>
 #include <linux/efi.h>
+#include <xen/guest_access.h>
+#include <asm/page.h>
+#include <public/memory.h>
 
 static void domain_page_flush(struct domain* d, unsigned long mpaddr,
                               unsigned long old_mfn, unsigned long new_mfn);
@@ -1752,6 +1755,83 @@ int memory_is_conventional_ram(paddr_t p)
     return (efi_mem_type(p) == EFI_CONVENTIONAL_MEMORY);
 }
 
+
+long
+arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
+{
+    switch (op) {
+    case XENMEM_add_to_physmap:
+    {
+        struct xen_add_to_physmap xatp;
+        unsigned long prev_mfn, mfn = 0, gpfn;
+        struct domain *d;
+
+        if (copy_from_guest(&xatp, arg, 1))
+            return -EFAULT;
+
+        if (xatp.domid == DOMID_SELF) {
+            d = current->domain;
+            get_knownalive_domain(d);
+        }
+        else if (!IS_PRIV(current->domain))
+            return -EPERM;
+        else if ((d = find_domain_by_id(xatp.domid)) == NULL)
+            return -ESRCH;
+
+        /* This hypercall is used for VT-i domain only */
+        if (!VMX_DOMAIN(d->vcpu[0])) {
+            put_domain(d);
+            return -ENOSYS;
+        }
+
+        switch (xatp.space) {
+        case XENMAPSPACE_shared_info:
+            if (xatp.idx == 0)
+                mfn = virt_to_mfn(d->shared_info);
+            break;
+        case XENMAPSPACE_grant_table:
+            if (xatp.idx < NR_GRANT_FRAMES)
+                mfn = virt_to_mfn(d->grant_table->shared) + xatp.idx;
+            break;
+        default:
+            break;
+        }
+
+        LOCK_BIGLOCK(d);
+
+        /* Remove previously mapped page if it was present. */
+        prev_mfn = gmfn_to_mfn(d, xatp.gpfn);
+        if (prev_mfn && mfn_valid(prev_mfn)) {
+            if (IS_XEN_HEAP_FRAME(mfn_to_page(prev_mfn)))
+                /* Xen heap frames are simply unhooked from this phys slot. */
+                guest_physmap_remove_page(d, xatp.gpfn, prev_mfn);
+            else
+                /* Normal domain memory is freed, to avoid leaking memory. */
+                guest_remove_page(d, xatp.gpfn);
+        }
+
+        /* Unmap from old location, if any. */
+        gpfn = get_gpfn_from_mfn(mfn);
+        if (gpfn != INVALID_M2P_ENTRY)
+            guest_physmap_remove_page(d, gpfn, mfn);
+
+        /* Map at new location. */
+        guest_physmap_add_page(d, xatp.gpfn, mfn);
+
+        UNLOCK_BIGLOCK(d);
+        
+        put_domain(d);
+
+        break;
+    }
+
+    default:
+        return -ENOSYS;
+    }
+
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
index 7df751c2c724d9856cec65e611ed39622c0b2567..f8db5c6e17aa4b54070e453291a4b62c6b7af003 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/page.h>
 #include <asm/vhpt.h>
 #include <asm/vcpu.h>
+#include <asm/vmmu.h>
 
 /* Defined in tlb.c  */
 extern void ia64_global_tlb_purge(UINT64 start, UINT64 end, UINT64 nbits);
@@ -131,15 +132,25 @@ void vhpt_init(void)
 
 void vcpu_flush_vtlb_all(struct vcpu *v)
 {
-       /* First VCPU tlb.  */
-       vcpu_purge_tr_entry(&PSCBX(v,dtlb));
-       vcpu_purge_tr_entry(&PSCBX(v,itlb));
+       if (VMX_DOMAIN(v)) {
+               /* This code may be call for remapping shared_info and
+                  grant_table share page from guest_physmap_remove_page()
+                  in arch_memory_op() XENMEM_add_to_physmap to realize
+                  PV-on-HVM feature. */
+               /* Purge vTLB for VT-i domain */
+               thash_purge_all(v);
+       }
+       else {
+               /* First VCPU tlb.  */
+               vcpu_purge_tr_entry(&PSCBX(v,dtlb));
+               vcpu_purge_tr_entry(&PSCBX(v,itlb));
 
-       /* Then VHPT.  */
-       vhpt_flush ();
+               /* Then VHPT.  */
+               vhpt_flush();
 
-       /* Then mTLB.  */
-       local_flush_tlb_all ();
+               /* Then mTLB.  */
+               local_flush_tlb_all();
+       }
 
        /* We could clear bit in d->domain_dirty_cpumask only if domain d in
           not running on this processor.  There is currently no easy way to